#include "common.h"
#include "stm8l15x_rtc.h"
#include <stdio.h>

extern char sleep_mode_start_work_flag;

RTC_InitTypeDef   RTC_InitStr;
RTC_TimeTypeDef   RTC_TimeStr;
RTC_DateTypeDef   RTC_DateStr;
RTC_AlarmTypeDef  RTC_AlarmStr;
uint8_t temp[12];

static uint8_t LastHour;

void rtc_init()
{
     /* Enable RTC clock */
   CLK_RTCClockConfig(CLK_RTCCLKSource_LSE, CLK_RTCCLKDiv_1);
   /* Wait for LSE clock to be ready */
   while (CLK_GetFlagStatus(CLK_FLAG_LSERDY) == RESET);
   /* wait for 1 second for the LSE Stabilisation */
   LSE_StabTime();
   CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);
  
   /* Configures the RTC wakeup timer_step = RTCCLK/16 = LSE/16 = 488.28125 us */
   //RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16);
  
   RTC_InitStr.RTC_HourFormat = RTC_HourFormat_24;
   RTC_InitStr.RTC_AsynchPrediv = 0x7F;
   RTC_InitStr.RTC_SynchPrediv = 0x00FF;
   RTC_Init(&RTC_InitStr);
   
#if 0
   rtc_sync_func(15, 1, 1, 12, 12, 30, 6);
#endif 
  
   /* Enable wake up unit Interrupt */
   RTC_ITConfig(RTC_IT_WUT, DISABLE);
   RTC_AlarmCmd(DISABLE);
}

static int rtc_set_curr_time(uint8_t hour, uint8_t min, uint8_t sec)
{
    int ret = 0;
    RTC_TimeStructInit(&RTC_TimeStr);
    if (hour > 24 || min > 60 || sec > 60)
       return -1;
        
    RTC_TimeStr.RTC_Hours   = hour;
    RTC_TimeStr.RTC_Minutes = min;
    RTC_TimeStr.RTC_Seconds = sec;
    RTC_SetTime(RTC_Format_BIN, &RTC_TimeStr);
    return ret;
}

static int rtc_set_curr_data(uint8_t year, uint8_t mon, uint8_t day, uint8_t weekday)
{
    int ret = 0;
    RTC_DateStructInit(&RTC_DateStr);
    
    if (mon>12 || day>31 || weekday>7)
       return -1;
    
    RTC_DateStr.RTC_Year  = year;
    RTC_DateStr.RTC_Month  =  mon;
    RTC_DateStr.RTC_Date  = day;
    RTC_DateStr.RTC_WeekDay = weekday;
    RTC_SetDate(RTC_Format_BIN, &RTC_DateStr);
    return ret;
}
   
int rtc_sync_func(uint8_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec, uint8_t weekday)
{
    if (rtc_set_curr_time(hour, min, sec) < 0)
      return -1;
    if (rtc_set_curr_data(year, mon, day, weekday) < 0)
      return -1;
    return 0;
}

void rtc_get_currtime(uint8_t *load_time)
{
    int temp1, temp2;
    RTC_GetTime(RTC_Format_BIN, &RTC_TimeStr);
    RTC_GetDate(RTC_Format_BIN, &RTC_DateStr);   

    load_time[0] = RTC_DateStr.RTC_Year;
    load_time[1] = RTC_DateStr.RTC_Month;
    load_time[2] = RTC_DateStr.RTC_Date;
    load_time[3] = RTC_TimeStr.RTC_Hours;
    load_time[4] = RTC_TimeStr.RTC_Minutes;
    load_time[5] = RTC_TimeStr.RTC_Seconds;
}

uint8_t rtc_get_which_day()
{
    RTC_GetDate(RTC_Format_BIN, &RTC_DateStr);
#if 0
    printf("day%d\r\n", RTC_DateStr.RTC_WeekDay & 0xff);
#endif    
    return RTC_DateStr.RTC_WeekDay;
}

int rtc_set_alarm(uint8_t hour, uint8_t min, uint8_t sec)
{
     RTC_AlarmCmd(DISABLE);
     RTC_AlarmStructInit(&RTC_AlarmStr);
     
     if (hour > 24 || min > 60 || sec > 60)
       return -1;
     
     RTC_AlarmStr.RTC_AlarmTime.RTC_Hours = hour;
     RTC_AlarmStr.RTC_AlarmTime.RTC_Minutes = min;
     RTC_AlarmStr.RTC_AlarmTime.RTC_Seconds = sec;
     RTC_AlarmStr.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;
     RTC_SetAlarm(RTC_Format_BIN,&RTC_AlarmStr);
     
     RTC_ITConfig(RTC_IT_ALRA, ENABLE);
     RTC_AlarmCmd(ENABLE);
     return 0;
}

static uint8_t alarm_confirm_flag = 0;
static uint8_t new_alarm_come = 0;
static uint8_t process_alarm;
void shutdown_alarm()
{
    alarm_confirm_flag = 1;
}

int rtc_callback(int value)
{
   if (value & EVENT_RTC_START)
   {
       set_timer_event(RTC_TASK, EVENT_RTC_TIMER, 100);
       value &= ~(EVENT_RTC_START);
   }
   
   if (value & EVENT_RTC_TIMER)
   {   
       /* for a hour alarm */ 
#if 0
       RTC_GetTime(RTC_Format_BIN, &RTC_TimeStr);
       if (LastHour != RTC_TimeStr.RTC_Seconds)
       {
          LastHour = RTC_TimeStr.RTC_Hours;
          set_event(STATICS_TASK, EVENT_DATA_UPDATE_HR);
       }
#endif     
       
#if 0
       uint8_t loadtime[6];
       rtc_get_currtime(loadtime);
       printf("%d/%d/%d, %d-%d-%d\r\n", loadtime[0], loadtime[1], loadtime[2], loadtime[3], loadtime[4], loadtime[5]);
       printf("alarm %d,%d,%d\r\n", RTC_AlarmStr.RTC_AlarmTime.RTC_Hours, RTC_AlarmStr.RTC_AlarmTime.RTC_Minutes,  RTC_AlarmStr.RTC_AlarmTime.RTC_Seconds );
       rtc_get_which_day();
      
       if (process_alarm)
       {
           if (alarm_confirm_flag)
           {
               printf("exit the alarm process\r\n");
               alarm_confirm_flag = 0;
               process_alarm = 0;
               motor_close();
               sleep_mode_start_work_flag = 0; // exit the steper sleep mode
           }
           else
           {
               motor_open();
           }
       }
#endif 
       set_timer_event(RTC_TASK, EVENT_RTC_TIMER, 100);
   }
   
   if (value & EVENT_RTC_ALARM_EXIT)
   {
       shutdown_alarm(); 
       value &= ~(EVENT_RTC_ALARM_EXIT);
   }
   
   if (value & EVENT_RTC_ALARM)
   {
       printf("alarm\r\n");
       
       process_alarm = 1;
       
       value &= ~(EVENT_RTC_ALARM);
   }
   
   if (value & EVENT_RTC_RECORD)
   {
       //printf("get a record event\r\n");
       temp[0] = 0xA0;
       rtc_get_currtime(&temp[1]);
       temp[7] = 0x1;
       USART1_SendString(temp, 8);
       led_set_mode(0x1);
       motor_shake(2);
       value &= ~(EVENT_RTC_RECORD);
   }
   
   if (value & EVENT_RTC_RECORD_END)
   {
       //printf("get a record_end event\r\n");
       temp[0] = 0xA0;
       rtc_get_currtime(&temp[1]);
       temp[7] = 0x0;
       USART1_SendString(temp, 8);
       led_set_mode(0x3);
       value &= ~(EVENT_RTC_RECORD_END);
   }

   return value;
}
